package com.bringspring.visualdev.onlinedev.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bringspring.common.base.UserInfo;
import com.bringspring.common.database.model.JdbcPageMod;
import com.bringspring.common.database.model.dto.PreparedStatementDTO;
import com.bringspring.common.database.model.entity.DbLinkEntity;
import com.bringspring.common.database.util.JdbcUtil;
import com.bringspring.common.exception.DataException;
import com.bringspring.common.model.visiual.*;
import com.bringspring.common.model.visiual.fields.FieLdsModel;
import com.bringspring.common.util.*;
import com.bringspring.common.util.context.SpringContext;
import com.bringspring.system.base.service.DblinkService;
import com.bringspring.system.permission.service.AuthorizeService;
import com.bringspring.visualdev.base.entity.VisualdevEntity;
import com.bringspring.visualdev.base.model.VisualWebTypeEnum;
import com.bringspring.visualdev.base.util.VisualUtils;
import com.bringspring.visualdev.onlinedev.entity.VisualdevModelDataEntity;
import com.bringspring.visualdev.onlinedev.mapper.VisualdevModelDataMapper;
import com.bringspring.visualdev.onlinedev.model.OnlineDevListModel.OnlineColumnFieldModel;
import com.bringspring.visualdev.onlinedev.model.OnlineDevListModel.OnlineDevListDataVO;
import com.bringspring.visualdev.onlinedev.model.OnlineDevListModel.OnlineFieldsModel;
import com.bringspring.visualdev.onlinedev.model.OnlineDevListModel.VisualColumnSearchVO;
import com.bringspring.visualdev.onlinedev.model.PaginationModel;
import com.bringspring.visualdev.onlinedev.service.VisualDevListService;
import com.bringspring.visualdev.onlinedev.util.onlineDevUtil.OnlineDevListUtils;
import com.bringspring.visualdev.onlinedev.util.onlineDevUtil.OnlineProductSqlUtils;
import com.bringspring.visualdev.onlinedev.util.onlineDevUtil.OnlinePublicUtils;
import com.bringspring.visualdev.onlinedev.util.onlineDevUtil.RelationFormUtils;
import com.bringspring.workflow.engine.entity.FlowTaskEntity;
import com.bringspring.workflow.engine.service.FlowTaskService;
import lombok.Cleanup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * 在线开发列表
 * @author 开发平台组
 * @version V1.0.0
 * @copyright 股份有限公司
 * @date  2021/7/28
 */
@Service
public class VisualDevListServiceImpl extends ServiceImpl<VisualdevModelDataMapper, VisualdevModelDataEntity> implements VisualDevListService {
	@Autowired
	private DblinkService dblinkService;
	@Autowired
	private FlowTaskService flowTaskService;
	@Autowired
	private UserProvider userProvider;

	@Override
	public List<Map<String, Object>> getDataList(VisualdevEntity visualdevEntity, PaginationModel paginationModel) {

		List<OnlineDevListDataVO> noSwapDataList;
		ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(),ColumnDataModel.class);
		FormDataModel formDataModel = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
		List<OnlineFieldsModel> swapDataVoList = JsonUtil.getJsonToList(formDataModel.getFields(),OnlineFieldsModel.class);
		List<FieLdsModel> fieLdsModels = JsonUtil.getJsonToList(formDataModel.getFields(), FieLdsModel.class);
		List<VisualColumnSearchVO> searchVOList = new ArrayList<>();
		//封装查询条件
		if (StringUtils.isNotEmpty(paginationModel.getQueryJson())){
			Map<String, Object> keyJsonMap = JsonUtil.stringToMap(paginationModel.getQueryJson());
			searchVOList= JsonUtil.getJsonToList(columnDataModel.getSearchList(),VisualColumnSearchVO.class);
			searchVOList =	searchVOList.stream().map(searchVO->{
				searchVO.setValue(keyJsonMap.get(searchVO.getVModel()));
				return searchVO;
			}).filter(vo->vo.getValue()!=null).collect(Collectors.toList());
			//左侧树查询
			boolean b =false;
			if (columnDataModel.getTreeRelation()!=null){
				b = keyJsonMap.keySet().stream().anyMatch(t -> t.equalsIgnoreCase(String.valueOf(columnDataModel.getTreeRelation())));
			}
			if (b && keyJsonMap.size()>searchVOList.size()){
				String relation =String.valueOf(columnDataModel.getTreeRelation());
				VisualColumnSearchVO vo =new VisualColumnSearchVO();
				//从列表控件中 赋予左侧树查询条件属性
				FieLdsModel fieLdsModel = fieLdsModels.stream().filter(swap -> relation.equalsIgnoreCase(swap.getVModel())).findFirst().orElse(null);
				vo.setConfig(Objects.nonNull(fieLdsModel) ? fieLdsModel.getConfig() : null);
				vo.setSearchType("1");
				vo.setVModel(relation);
				vo.setValue(keyJsonMap.get(relation));
				searchVOList.add(vo);
			}
		}
		//判断有无表
		if (OnlinePublicUtils.isUseTables(visualdevEntity.getVisualTables())){
			//当前用户信息
			UserInfo userInfo = userProvider.get();
			//菜单id
			String moduleId = paginationModel.getMenuId();
			String reg = "^[jsbos_]\\S*_jsbos\\S*";
			searchVOList.stream().filter(c-> c.getVModel().matches(reg)).forEach(
					cl->{
						String s = cl.getVModel();
						String s1 = s.substring(s.lastIndexOf("jsbos_")).replace("jsbos_","");
						cl.setVModel(s1);
					}
			);
			noSwapDataList =this.getListWithTable(visualdevEntity,paginationModel,userInfo,moduleId,searchVOList);
		}else{
			noSwapDataList =this.getWithoutTableData(visualdevEntity.getId());
			noSwapDataList = this.getList(noSwapDataList, searchVOList, paginationModel);
		}
		List<Map<String, Object>> realList =new ArrayList<>();
		if (noSwapDataList.size()<1){
			return realList;
		}

		//递归处理控件
		List<OnlineFieldsModel> allFormDataModelList = new ArrayList<>();
		OnlinePublicUtils.recursionFields(swapDataVoList,allFormDataModelList);
		allFormDataModelList=allFormDataModelList.stream().filter(model->model.getConfig().getKeyName()!=null && StringUtils.isNotEmpty(model.getVModel())).collect(Collectors.toList());
		//数据转换
		noSwapDataList = OnlineDevListUtils.getSwapList(noSwapDataList, allFormDataModelList,visualdevEntity.getId());

			 realList = noSwapDataList.stream().map(t -> {
				t.getData().put("id",t.getId());
				return t.getData();
			}).collect(Collectors.toList());

			//添加流程状态
				if(visualdevEntity.getWebType()!=null){
				if (visualdevEntity.getWebType().equals(VisualWebTypeEnum.FLOW_FROM.getType())){
					List<String> ids = realList.stream().map(i->i.get("id").toString()).collect(Collectors.toList());
					List<FlowTaskEntity> tasks = flowTaskService.getInfosSubmit(ids.toArray(new String[]{}), FlowTaskEntity::getStatus, FlowTaskEntity::getId, FlowTaskEntity::getProcessId);
					realList.stream().forEach(m->{
						String id = m.get("id").toString();
						m.put("flowState","");
						tasks.forEach(i->{
							if(i.getId().equals(id) || i.getProcessId().equals(id)){
								m.put("flowState", i.getStatus());
							}
						});
					});
				}
			}
		return realList;
	}

	@Override
	public List<OnlineDevListDataVO> getList(List<OnlineDevListDataVO> noSwapDataList, List<VisualColumnSearchVO> searchVOList, PaginationModel paginationModel) {
		if (searchVOList.size() > 0) {
			//条件查询
			noSwapDataList = OnlineDevListUtils.getNoSwapList(noSwapDataList, searchVOList);
		}
		//排序
		if (noSwapDataList.size() > 0) {
			if (StringUtils.isNotEmpty(paginationModel.getSidx())) {
				//排序处理
				noSwapDataList.sort((o1, o2) -> {
					Map<String, Object> i1 = o1.getData();
					Map<String, Object> i2 = o2.getData();
					String s1 = String.valueOf(i1.get(paginationModel.getSidx()));
					String s2 = String.valueOf(i2.get(paginationModel.getSidx()));
					if ("desc".equalsIgnoreCase(paginationModel.getSort())) {
						return s2.compareTo(s1);
					} else {
						return s1.compareTo(s2);
					}
				});
			}

			long total = noSwapDataList.size();

			//数据分页
			noSwapDataList = PageUtil.getListPage((int) paginationModel.getCurrentPage(), (int) paginationModel.getPageSize(), noSwapDataList);
			noSwapDataList = paginationModel.setData(noSwapDataList, total);
		}
		return noSwapDataList;
	}

	@Override
	public List<OnlineDevListDataVO> getWithoutTableData(String modelId) {
		QueryWrapper<VisualdevModelDataEntity> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(VisualdevModelDataEntity::getVisualDevId, modelId);
		List<VisualdevModelDataEntity> list = this.list(queryWrapper);
		List<OnlineDevListDataVO> dataVoList = list.parallelStream().map(t -> {
			OnlineDevListDataVO vo = new OnlineDevListDataVO();
			vo.setId(t.getId());
			vo.setData(JsonUtil.stringToMap(t.getData()));
			return vo;
		}).collect(Collectors.toList());
		return dataVoList;
	}

	@Override
	public List<OnlineDevListDataVO> getListWithTable(VisualdevEntity visualdevEntity, PaginationModel paginationModel,
																										UserInfo userInfo,String moduleId,List<VisualColumnSearchVO> searchVOList) {

		List<OnlineDevListDataVO> noSwapDataList = new ArrayList<>();

		//数据源
		DbLinkEntity linkEntity = dblinkService.getInfo(visualdevEntity.getDbLinkId());

		ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getAppColumnData(),ColumnDataModel.class);

		//判断请求客户端来源
		String header = ServletUtils.getHeader("jsbos-origin");

		if ("pc".equals(header)){
			columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(),ColumnDataModel.class);
		}

		List<TableModel> tableModelList = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(),TableModel.class);
		//主表
		TableModel mainTable = tableModelList.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);

		List<ColumnListField> modelList = JsonUtil.getJsonToList(columnDataModel.getColumnList(), ColumnListField.class);

		StringBuilder mainSql = new StringBuilder();

		//所有字段
		List<String> collect = modelList.stream().map(mode -> mode.getProp()).collect(Collectors.toList());

		mainSql= OnlineProductSqlUtils.getColumnListSql(mainSql,tableModelList,collect,linkEntity);

		mainSql.append(" where (1=1)");

		//数据权限
			if (columnDataModel.getUseDataPermission()!=null && columnDataModel.getUseDataPermission()){
				//数据权限
				AuthorizeService authorizeService = SpringContext.getBean(AuthorizeService.class);
				if (!userInfo.getIsAdministrator()) {
					String conditionSql = authorizeService.getConditionSql(userInfo, moduleId, mainTable.getTable());
					if (conditionSql.length()>0){
						if (!conditionSql.equals("alldata")){
							mainSql.append(conditionSql);
						}
					}
					//未分配方案不显示数据
					else {
						return new ArrayList<>();
					}
				}
			}

		try {
			@Cleanup Connection connection = VisualUtils.getDataConn(linkEntity);
			if (searchVOList.size()>0){
				//查询条件sql
				mainSql= OnlineProductSqlUtils.getConditionSql(mainSql, linkEntity, searchVOList, mainTable.getTable());
			}
			String pkeyId = VisualUtils.getpKey(connection, mainTable.getTable());
			String sort;
			if (StringUtils.isNotEmpty(paginationModel.getSort())){
				 sort = paginationModel.getSort();
			}else {
				sort = "ASC";
			}
			String sidx=pkeyId;
			if (StringUtils.isNotEmpty(paginationModel.getSidx())){
				sidx = paginationModel.getSidx();
			}
			String sortType = sidx + " " + sort;
			List<Map<String,Object>> dataList;
			//是否导出全部数据
			if ("1".equals(paginationModel.getDataType())){
				dataList = JdbcUtil.queryListAlias(new PreparedStatementDTO(connection,mainSql.toString()));
			}else {
				JdbcPageMod jdbcPageMod = JdbcUtil.queryPage(new PreparedStatementDTO(connection, mainSql.toString()), sortType, (int) paginationModel.getCurrentPage(), (int) paginationModel.getPageSize());
				dataList = jdbcPageMod.getDataList();
				paginationModel.setTotal(jdbcPageMod.getTotalRecord());
			}
			List<OnlineColumnFieldModel> childValue = OnlineProductSqlUtils.getChildValue(collect);
			dataList=dataList.stream().map(map -> {
				map = OnlinePublicUtils.mapKeyToLower(map);
				Map<String,Object> realMap = new HashMap<>();
					for (OnlineColumnFieldModel onlineColumnFieldModel : childValue ){
						realMap.put(onlineColumnFieldModel.getOriginallyField(),map.get(onlineColumnFieldModel.getOtherName().toLowerCase()));
					}
					realMap.put(pkeyId.toLowerCase(),map.get(pkeyId.toLowerCase()));
					return realMap;
			}).collect(Collectors.toList());

			noSwapDataList = 	dataList.stream().map(data ->  {
				OnlineDevListDataVO vo =new OnlineDevListDataVO();
				vo.setId(String.valueOf(data.get(pkeyId.toLowerCase())));
				vo.setData(data);
				return vo;
			}).collect(Collectors.toList());

		} catch (SQLException | DataException sqlException) {
			sqlException.printStackTrace();
		}
		return noSwapDataList;
	}

	@Override
	public List<Map<String, Object>> getRelationFormList(VisualdevEntity entity, PaginationModel paginationModel) {
		FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
		List<String> collect= Arrays.asList(paginationModel.getColumnOptions().split(","));
		List<OnlineFieldsModel> fieLdsModelList = JsonUtil.getJsonToList(formData.getFields(), OnlineFieldsModel.class);
		List<FieLdsModel> fieLdsModels = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
		List<OnlineFieldsModel> childFieldModelList = new ArrayList<>();
		List<OnlineFieldsModel> mainFieldModelList = new ArrayList<>();

		OnlinePublicUtils.recurseOnlineFiled(fieLdsModelList, mainFieldModelList,childFieldModelList);

		//去除不必要的控件
		mainFieldModelList=mainFieldModelList.stream().filter(fieLdsModel -> !"".equals(fieLdsModel.getVModel()) && StringUtils.isNotEmpty(fieLdsModel.getVModel())
				&& !ComponentKeyConsts.RELATIONFORM.equals(fieLdsModel.getConfig().getKeyName())).collect(Collectors.toList());

		List<OnlineDevListDataVO> noSwapDataList = new ArrayList<>();
		List<VisualColumnSearchVO> searchVOList = new ArrayList<>();
		//查询的关键字
		String keyword = paginationModel.getKeyword();
		//判断有无表
		if (OnlinePublicUtils.isUseTables(entity.getVisualTables())){
			try{
				List<TableModel> tableModelList = JsonUtil.getJsonToList(entity.getVisualTables(),TableModel.class);
				//主表
				TableModel mainTable = tableModelList.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);

				DbLinkEntity linkEntity = dblinkService.getInfo(entity.getDbLinkId());

				List<OnlineColumnFieldModel> childValue = OnlineProductSqlUtils.getChildValue(collect);

				StringBuilder sql =new StringBuilder();

				//判断是否分页
				Boolean isPage =  paginationModel.getPageSize()>500 ? false : true;

				sql=OnlineProductSqlUtils.getColumnListSql(sql,tableModelList,collect,linkEntity);
				@Cleanup Connection connection = VisualUtils.getDataConn(linkEntity);

				//第一种 有关键字查询并且分页的查询
				if (StringUtils.isNotEmpty(keyword) && isPage) {
					//只取 单行 多行可输入的值
					for (FieLdsModel fieldsModel : fieLdsModels){
						if (fieldsModel.getVModel()!=null){
							boolean b = collect.stream().anyMatch(c ->
									fieldsModel.getVModel().equalsIgnoreCase(c)
											&& (fieldsModel.getConfig().getKeyName().equals(ComponentKeyConsts.COM_INPUT)
											|| fieldsModel.getConfig().getKeyName().equals(ComponentKeyConsts.TEXTAREA)));
							//组装为查询条件
							if (b){
								VisualColumnSearchVO vo =new VisualColumnSearchVO();
								vo.setSearchType("2");
								vo.setVModel(fieldsModel.getVModel());
								vo.setValue(keyword);
								vo.setConfig(fieldsModel.getConfig());
								Boolean multiple = fieldsModel.getMultiple();
								vo.setMultiple(multiple);
								searchVOList.add(vo);
							}
						}
					}

					if (searchVOList.size()>0){
						sql = RelationFormUtils.getRelationListByKeywordWithSql(sql,searchVOList,mainTable.getTable());
					}
				}

				String pkeyId = VisualUtils.getpKey(connection, mainTable.getTable());
				String sort;
				if (StringUtils.isNotEmpty(paginationModel.getSort())){
					sort = paginationModel.getSort();
				}else {
					sort = "ASC";
				}
				String sidx=pkeyId;
				if (StringUtils.isNotEmpty(paginationModel.getSidx())){
					sidx = paginationModel.getSidx();
				}
				String sortType = sidx + " " + sort;
				JdbcPageMod jdbcPageMod = JdbcUtil.queryPage(new PreparedStatementDTO(connection, sql.toString()), sortType, (int) paginationModel.getCurrentPage(), (int) paginationModel.getPageSize());
				List<Map<String,Object>> dataList = jdbcPageMod.getDataList();

				dataList=dataList.stream().map(map -> {
					map = OnlinePublicUtils.mapKeyToLower(map);
					Map<String,Object> realMap = new HashMap<>();
					for (OnlineColumnFieldModel onlineColumnFieldModel : childValue ){
						realMap.put(onlineColumnFieldModel.getOriginallyField(),map.get(onlineColumnFieldModel.getOtherName().toLowerCase()));
					}
					realMap.put(pkeyId.toLowerCase(),map.get(pkeyId.toLowerCase()));
					return realMap;
				}).collect(Collectors.toList());

				paginationModel.setTotal(jdbcPageMod.getTotalRecord());

				noSwapDataList = 	dataList.stream().map(data ->  {
					OnlineDevListDataVO vo =new OnlineDevListDataVO();
					vo.setId(String.valueOf(data.get(pkeyId.toLowerCase())));
					vo.setData(data);
					return vo;
				}).collect(Collectors.toList());

				//第二种 有关键字不分页
				if (StringUtils.isNotEmpty(keyword) && !isPage){
					for (FieLdsModel fieldsModel : fieLdsModels){
						if (fieldsModel.getVModel()!=null){
							boolean b = collect.stream().anyMatch(c ->
									fieldsModel.getVModel().equalsIgnoreCase(c)
							);
							//组装为查询条件
							if (b){
								VisualColumnSearchVO vo =new VisualColumnSearchVO();
								vo.setSearchType("2");
								vo.setVModel(fieldsModel.getVModel());
								vo.setValue(keyword);
								vo.setConfig(fieldsModel.getConfig());
								Boolean multiple = fieldsModel.getMultiple();
								vo.setMultiple(multiple);
								searchVOList.add(vo);
							}
						}
					}
					noSwapDataList = OnlineDevListUtils.getSwapList(noSwapDataList, mainFieldModelList,entity.getId());

					noSwapDataList= RelationFormUtils.getRelationListByKeyword(noSwapDataList, searchVOList);
				}else {
					noSwapDataList = OnlineDevListUtils.getSwapList(noSwapDataList, mainFieldModelList,entity.getId());
				}

			} catch (SQLException | DataException sqlException) {
				sqlException.printStackTrace();
			}
		}
		//无表
		else{
			if (StringUtils.isNotEmpty(keyword)){
				for (FieLdsModel fieldsModel : fieLdsModels){
					if (fieldsModel.getVModel()!=null){
						boolean b = collect.stream().anyMatch(c ->
								fieldsModel.getVModel().equalsIgnoreCase(c)
						);
						//组装为查询条件
						if (b){
							VisualColumnSearchVO vo =new VisualColumnSearchVO();
							vo.setSearchType("2");
							vo.setVModel(fieldsModel.getVModel());
							vo.setValue(keyword);
							vo.setConfig(fieldsModel.getConfig());
							Boolean multiple = fieldsModel.getMultiple();
							vo.setMultiple(multiple);
							searchVOList.add(vo);
						}
					}
				}
			}
			noSwapDataList =this.getWithoutTableData(entity.getId());

			noSwapDataList = OnlineDevListUtils.getSwapList(noSwapDataList, mainFieldModelList,entity.getId());
			if (searchVOList.size()>0){
				noSwapDataList = RelationFormUtils.getRelationListByKeyword(noSwapDataList, searchVOList);
			}
		}
		if (noSwapDataList.size()<1){
			return new ArrayList<>();
		}
		return noSwapDataList.stream().map(t -> {
			Map<String, Object> data = t.getData();
			data.put("id",t.getId());
			return data;
		}).collect(Collectors.toList());
	}
}
